package com.shanzmoo.base.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;

import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.function.Consumer;

/**
 * @author fs
 */
@Slf4j
@Component
@Import(cn.hutool.extra.spring.SpringUtil.class)
public class SpringUtil implements ApplicationContextAware {
    private static ApplicationContext applicationContext;
    private static List<Consumer<ApplicationContext>> needInitList = new Vector<>();
    public static <T> T getBean(Class<T> clazz){
        return getBean(null,clazz);
    }
    public static <T> T getBean(String name){
        return getBean(name,null);
    }
    public static <T> T getBean(String name,Class<T> clazz){
        if(applicationContext == null){
            return null;
        }
        if(name != null && clazz != null){
            return applicationContext.getBean(name,clazz);
        }else if(name != null){
            return (T)applicationContext.getBean(name);
        }else if(clazz != null){
            return applicationContext.getBean(clazz);
        }else{
            return null;
        }
    }
    public static <T> void asyncGetBean(Class<T> clazz,Consumer<T> consumer){
        asyncGetBean(null,clazz,consumer);
    }
    public static <T> void asyncGetBean(String name,Consumer<T> consumer){
        asyncGetBean(name,null,consumer);
    }
    public static <T> void asyncGetBean(final String name,final Class<T> clazz,final Consumer<T> consumer){
        asyncAction(new Consumer<ApplicationContext>() {
            @Override
            public void accept(ApplicationContext applicationContext) {
                T t = getBean(name,clazz);
                consumer.accept(t);
            }
        });
    }
    public static void asyncAction(Consumer<ApplicationContext> consumer){
        if(SpringUtil.applicationContext == null){
            SpringUtil.needInitList.add(consumer);
        }else{
            action(consumer);
        }
    }
    public static ApplicationContext getApplicationContext(){
        return SpringUtil.applicationContext;
    }
    private static void action(Consumer<ApplicationContext> consumer){
        try{
            consumer.accept(SpringUtil.applicationContext);
        }catch (Exception e){
            log.error("SpringIoc执行失败",e);
        }
    }
    private static void init(){
        if(SpringUtil.needInitList.size()>0){
            Iterator<Consumer<ApplicationContext>> it= SpringUtil.needInitList.iterator();
            while(it.hasNext()){
                action(it.next());
                it.remove();
            }
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringUtil.applicationContext = applicationContext;
        SpringUtil.init();
    }
}
